/* hal_dma.c */
#include "hal_dma.h"

static void DMA_ResetCtsRegisters(DMA_Type * base, uint32_t channel);

void DMA_InitController(DMA_Type * base, DMA_ControllerInit_Type * init)
{
    uint32_t tmp32 = base->CTRL & ~(DMA_CTRL_LOEN_MASK | DMA_CTRL_CLM_MASK | DMA_CTRL_DBGDIS_MASK);

    if (init->EnableMinorLoopOffset)
    {
    	tmp32 |= DMA_CTRL_LOEN_MASK;
    }

    if (init->EnableContinuousLinkMode)
    {
    	tmp32 |= DMA_CTRL_CLM_MASK;
    }

    if (!init->EnableKeepTransOnDebug)
    {
    	tmp32 |= DMA_CTRL_DBGDIS_MASK;
    }

    base->CTRL = tmp32;
    
    for (uint32_t i = 0u; i < DMA_CTS_COUNT; i++)
    {
        DMA_ResetCtsRegisters(base, i);
    }
}

void DMA_SetChannelTrigger(DMA_Type * base, uint32_t channel, uint32_t dmamux)
{
	base->CHMUX[channel] = dmamux;
}

void DMA_SetChannelTransStruct(DMA_Type * base, uint32_t channel, DMA_ChannelTransStruct_Type * cts)
{
    DMA_ResetCtsRegisters(base, channel);
    
    base->CTS[channel].SADDR = cts->SourceAddr;
    base->CTS[channel].SOFF = cts->SourceAddrOffsetOnTrans;
    base->CTS[channel].STO = cts->SourceAddrOffsetOnMajorLoop;
    
    base->CTS[channel].TCR = DMA_CTS_TCR_SSIZE(cts->SourceTransDataWidth) | DMA_CTS_TCR_DSIZE(cts->DestTransDataWidth);
    
    base->CTS[channel].DADDR = cts->DestAddr;
    base->CTS[channel].DOFF = cts->DestAddrOffsetOnTrans;
    base->CTS[channel].DTO_RLD.DTO = cts->DestAddrOffsetOnMajorLoop;

    
    base->CTS[channel].BCNT.BCNT = cts->MinorLoopByteCount;
    base->CTS[channel].TCNT.LKDIS = cts->MajorLoopCount;
    base->CTS[channel].TCNTRV = cts->MajorLoopCount;
    
    /* dma_cts_csr. */
    uint32_t tmp32 = 0u;

    if (cts->EnableInterruptOnMajorLoopDone)
    {
        tmp32 |= DMA_CTS_CSR_TDINT_MASK;
    }
    if (cts->EnableInterruptOnMajorLoopHalfDone)
    {
        tmp32 |= DMA_CTS_CSR_THDINT_MASK;
    }

    if (cts->EnableInterruptOnMinorLoopDone)
    {
        tmp32 |= DMA_CTS_CSR_LOOPINT_MASK;
    }
    if (cts->EnableAutoDisableChannelReqOnMajorLoopDone)
    {
        tmp32 |= DMA_CTS_CSR_DREQ_MASK;
    }
#if 1
    if (cts->EnableReloadRamConf)
    {
        tmp32 |= DMA_CTS_CSR_RLDEN_MASK;
        
        //base->CTS[channel].DTO_RLD.RLD = cts->NextCts; /* MajorLoopCountReload */
    }
#endif
    base->CTS[channel].CSR = tmp32;
}

void DMA_EnableChannelReqs(DMA_Type * base, uint32_t channels)
{
    base->REQEN |= channels;
}

void DMA_DisableChannelReqs(DMA_Type * base, uint32_t channels)
{
    base->REQEN &= ~channels;
}


uint32_t DMA_GetMajorLoopDoneChannels(DMA_Type * base)
{
    return base->CHTLDIF;
}

void DMA_ClearMajorLoopDoneChannels(DMA_Type * base, uint32_t channels)
{
    base->CHTLDIF = channels;
}

uint32_t DMA_GetMajorLoopHalfDoneChannels(DMA_Type * base)
{
    return base->CHTLHDIF;
}

void DMA_ClearMajorHalfDoneChannels(DMA_Type * base, uint32_t channels)
{
    base->CHTLHDIF = channels;
}

uint32_t DMA_GetMinorLoopDoneChannels(DMA_Type * base)
{
    return base->DONE;
}

void DMA_ClearMinorLoopDoneChannels(DMA_Type * base, uint32_t channels)
{
    base->DONE = channels;
}

void DMA_DoSoftwareTriggerChannels(DMA_Type * base, uint32_t channels)
{
    base->START = channels;
}

static void DMA_ResetCtsRegisters(DMA_Type * base, uint32_t channel)
{
    base->CTS[channel].SADDR = 0u;
    base->CTS[channel].SOFF = 0u;
    base->CTS[channel].TCR = 0u;
    base->CTS[channel].BCNT.BCNT = 0;
    base->CTS[channel].STO = 0;
    base->CTS[channel].DADDR = 0;
    base->CTS[channel].DOFF = 0;
    base->CTS[channel].TCNT.LKDIS = 0;
    base->CTS[channel].DTO_RLD.DTO = 0;
    base->CTS[channel].CSR = 0;
    base->CTS[channel].TCNTRV = 0;
}

/* EOF. */

